#ifndef CODE_GEN_X86_H
#define CODE_GEN_X86_H

#include "Assembly_x86.h"

namespace Compiler
{
	namespace x86
	{
		using namespace CoreLib::Basic;

		class BinaryCodeEmitter
		{
		private:
			List<unsigned char> code;
			void EmitInstruction(int opLen, const char * opCode, unsigned char opCodePlus, unsigned char extDigit, Operand op);
			void EmitInstruction(int opLen, const char * opCode, unsigned char opCodePlus, Register reg, Operand op);	
		public:
			int Size()
			{
				return code.Count();
			}
			List<unsigned char> && GetCode()
			{
				return _Move(code);
			}
			void Emit(const Instruction & instr);
			void Emit_ADC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_ADD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_AND(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_BOUND(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_BSF(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_BSR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_BSWAP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_BT(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_BTC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_BTR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_BTS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CALL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CBW(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CDQ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CLC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CLD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CLI(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVAE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVBE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVG(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVGE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVLE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNAE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNBE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNG(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNGE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNLE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVNZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVPE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVPO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMOVZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMPSB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMPSD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CMPSW(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CWD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_CWDE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_DEC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_DIV(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_F2XM1(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FABS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FADD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FADDP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCHS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCMOVB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCMOVBE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCMOVE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCMOVNB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCMOVNBE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCMOVNE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCMOVNU(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCMOVU(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCOM(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCOMI(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCOMIP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCOMP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCOMPP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FCOS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FDECSTP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FDIV(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FDIVP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FDIVR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FDIVRP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FIADD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FICOM(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FICOMP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FIDIV(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FIDIVR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FILD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FIMUL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FINCSTP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FINIT(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FIST(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FISTP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FISTTP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FISUB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FISUBR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FLD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FLD1(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FLDL2E(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FLDL2T(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FLDLG2(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FLDLN2(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FLDPI(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FLDZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FMUL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FMULP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FNINIT(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FNSTSW(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FPATAN(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FRNDINT(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSCALE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSIN(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSINCOS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSQRT(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FST(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSTP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSTSW(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSUB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSUBP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSUBR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FSUBRP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FTST(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FUCOM(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FUCOMI(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FUCOMIP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FUCOMP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FUCOMPP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FXAM(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FXCH(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FXTRACT(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FYL2X(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_FYL2XP1(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_IDIV(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_IMUL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_INC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_INT(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_INTO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JAE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JBE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JCXZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JECXZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JG(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JGE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JLE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JMP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNAE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNBE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNG(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNGE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNLE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JNZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JPE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JPO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_JZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LEA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LODSB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LODSD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LODSW(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LOOP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LOOPE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LOOPNE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LOOPNZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_LOOPZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_MOV(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_MOVSB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_MOVSD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_MOVSW(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_MOVZX(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_MUL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_NEG(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_NOT(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_OR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_POP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_POPA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_POPAD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_PUSH(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_PUSHA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_PUSHAD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_RCL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_RCR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_RET(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_ROL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_ROR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SAHF(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SAL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SAR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SBB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SCASB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SCASD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SCASW(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETAE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETBE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETG(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETGE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETLE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNA(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNAE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNBE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNG(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNGE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNLE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETNZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETP(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETPE(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETPO(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETS(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SETZ(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SHL(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SHR(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_STC(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_STD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_STI(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_STOSB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_STOSD(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_STOSW(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_SUB(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_TEST(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_XCHG(int paramCount, const Operand & op1, const Operand & op2);
			void Emit_XOR(int paramCount, const Operand & op1, const Operand & op2);

			void EmitLoad(Register dest, int offset);
			void EmitStore(Register source, int offset);
			void * ToFunc();
		};
	}
}

#endif